package hn.cch.framework.util;

import com.sun.mail.util.MailSSLSocketFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.activation.FileDataSource;
import javax.activation.MimeType;
import javax.mail.Authenticator;
import javax.mail.BodyPart;
import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.Multipart;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Store;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import javax.mail.internet.MimeUtility;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.Date;
import java.util.List;
import java.util.Properties;

public class MailUtil {

    private static Logger logger = LoggerFactory.getLogger(MailUtil.class);

    private String protocol;//协议
    private String host;//主机
    private String port;//端口
    private String user;//用户
    private String password;//密码


    public static Session initMail(MailUtil mailUtil) {
        try {

            Properties properties = new Properties();
            String protocol = mailUtil.getProtocol();
            properties.put("mail.store.protocol", protocol);
            properties.put("mail." + protocol + ".host", mailUtil.getHost());
            properties.put("mail." + protocol + ".port", mailUtil.getPort());

            MailSSLSocketFactory mailSSLSocketFactory = new MailSSLSocketFactory();
            mailSSLSocketFactory.setTrustAllHosts(true);
            properties.put("mail." + protocol + ".ssl.enable", "true");
            properties.put("mail." + protocol + ".ssl.socketFactory", mailSSLSocketFactory);

            Session session = Session.getDefaultInstance(properties, new Authenticator() {
                @Override
                protected PasswordAuthentication getPasswordAuthentication() {
                    PasswordAuthentication passwordAuthentication = new PasswordAuthentication(mailUtil.getUser(), mailUtil.getPassword());
                    return passwordAuthentication;
                }
            });
            session.setDebug(true);


            return session;
        } catch (Exception e) {
            logger.error(e.getMessage());
            return null;
        }
    }


    /**
     * @param session
     */
    public static void readMail(Session session) {
        try {
            Store store = session.getStore();
            store.connect();
            Folder folder = store.getFolder("INBOX");
            folder.open(Folder.READ_WRITE);
            Message[] messages = folder.getMessages();
            logger.info(" messages.length={}", messages.length);
            for (Message message : messages) {
                parseMessage(message);
            }

        } catch (Exception e) {
            logger.error(e.getMessage());
        }
    }

    /**
     * 解析Message
     *
     * @param message
     */
    public static void parseMessage(Message message) {

        try {
            String subject = message.getSubject();//主题
            Date sentDate = message.getSentDate();//发送日期
            logger.info("Subject:{}|SendDate:{}", subject, sentDate);
            Object content = message.getContent();
            if (content instanceof MimeMultipart) {
                MimeMultipart multipart = (MimeMultipart) content;
                parseMultipart(multipart);
            }
        } catch (Exception e) {
            logger.error(e.getMessage());
        }

    }

    /**
     * 解析Multipart
     *
     * @param multipart
     */
    public static void parseMultipart(Multipart multipart) {

        try {
            int count = multipart.getCount();
            for (int i = 0; i < count; i++) {
                BodyPart bodyPart = multipart.getBodyPart(i);
                logger.info("ContentType:{}", bodyPart.getContentType());
                if (bodyPart.isMimeType("text/*")) {//文本
                    logger.info("text:{}", bodyPart.getContent());
                } else if (bodyPart.isMimeType("application/octet-stream")) {
                    String disposition = bodyPart.getDisposition();
                    logger.info("disposition:{}", disposition);
                    if (disposition.equalsIgnoreCase(BodyPart.ATTACHMENT)) {// 邮件附件
                        String fileName = bodyPart.getFileName();
                        FileOutputStream outputStream = new FileOutputStream(fileName);
                        InputStream inputStream = bodyPart.getInputStream();
                        // byte[] bytes = FileUtil.toBytes(inputStream);
                        // FileUtil.fromBytes(outputStream, bytes);//保存文件
                    }
                } else if (bodyPart.isMimeType("multipart/*")) {//递归调用
                    MimeMultipart mimeMultipart = (MimeMultipart) bodyPart.getContent();
                    parseMultipart(mimeMultipart);
                }

            }
        } catch (Exception e) {
            logger.error(e.getMessage());
        }
    }


    /**
     * @param session
     * @param recipient
     * @param personal
     * @param subject
     */
    public static void sendMail(Session session, String recipient, String personal, String subject) {

        try {
            Transport transport = session.getTransport();

            Message message = new MimeMessage(session);
            InternetAddress to = new InternetAddress(recipient);
            to.setPersonal(personal);
            message.addRecipient(Message.RecipientType.TO, to);//收件人
            message.addRecipient(Message.RecipientType.TO, to);//抄送
            message.addRecipient(Message.RecipientType.TO, to);//密抄
            message.setSubject(MimeUtility.encodeText(subject));
            message.setSentDate(new Date());
            // 添加正文

            // 添加附件

            message.saveChanges();
            transport.sendMessage(message, message.getAllRecipients());
            transport.close();

        } catch (Exception e) {
            logger.error(e.getMessage());
        }
    }

    /**
     * 添加正文
     * @param message
     * @param content
     * @param isPlain
     */
    public static void addContent(Message message, String content, Boolean isPlain) {
        try {
            if (isPlain) {
                message.setContent(content, "text/plain;charset=UTF-8");
            } else {
                message.setContent(content, "text/html;charset=UTF-8");
            }
        } catch (Exception e) {
            logger.error(e.getMessage());

        }
    }

    /**
     * 添加附件
     *
     * @param message
     * @param fileList
     */
    public static void addAttachment(Message message, List<File> fileList) {
        try {
            Multipart multipart = new MimeMultipart();
            for (File file : fileList) {
                MimeBodyPart mimeBodyPart = new MimeBodyPart();
                DataSource source = new FileDataSource(file);
                mimeBodyPart.setDataHandler(new DataHandler(source));
                mimeBodyPart.setFileName(MimeUtility.encodeWord(file.getName()));
                multipart.addBodyPart(mimeBodyPart);
            }
            message.setContent(multipart);
            message.saveChanges();
        } catch (Exception e) {
            logger.error(e.getMessage());
        }
    }


    public String getProtocol() {
        return protocol;
    }

    public void setProtocol(String protocol) {
        this.protocol = protocol;
    }

    public String getHost() {
        return host;
    }

    public void setHost(String host) {
        this.host = host;
    }

    public String getPort() {
        return port;
    }

    public void setPort(String port) {
        this.port = port;
    }

    public String getUser() {
        return user;
    }

    public void setUser(String user) {
        this.user = user;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}
